<!-- HTML header for doxygen 1.8.6-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.13"/>
<title>OpenCV: Omnidirectional Camera Calibration</title>
<link href="../../opencv.ico" rel="shortcut icon" type="image/x-icon" />
<link href="../../tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../jquery.js"></script>
<script type="text/javascript" src="../../dynsections.js"></script>
<script type="text/javascript" src="../../tutorial-utils.js"></script>
<link href="../../search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="../../search/searchdata.js"></script>
<script type="text/javascript" src="../../search/search.js"></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    extensions: ["tex2jax.js", "TeX/AMSmath.js", "TeX/AMSsymbols.js"],
    jax: ["input/TeX","output/HTML-CSS"],
});
//<![CDATA[
MathJax.Hub.Config(
{
  TeX: {
      Macros: {
          matTT: [ "\\[ \\left|\\begin{array}{ccc} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{array}\\right| \\]", 9],
          fork: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ \\end{array} \\right.", 4],
          forkthree: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ \\end{array} \\right.", 6],
          forkfour: ["\\left\\{ \\begin{array}{l l} #1 & \\mbox{#2}\\\\ #3 & \\mbox{#4}\\\\ #5 & \\mbox{#6}\\\\ #7 & \\mbox{#8}\\\\ \\end{array} \\right.", 8],
          vecthree: ["\\begin{bmatrix} #1\\\\ #2\\\\ #3 \\end{bmatrix}", 3],
          vecthreethree: ["\\begin{bmatrix} #1 & #2 & #3\\\\ #4 & #5 & #6\\\\ #7 & #8 & #9 \\end{bmatrix}", 9],
          cameramatrix: ["#1 = \\begin{bmatrix} f_x & 0 & c_x\\\\ 0 & f_y & c_y\\\\ 0 & 0 & 1 \\end{bmatrix}", 1],
          distcoeffs: ["(k_1, k_2, p_1, p_2[, k_3[, k_4, k_5, k_6 [, s_1, s_2, s_3, s_4[, \\tau_x, \\tau_y]]]]) \\text{ of 4, 5, 8, 12 or 14 elements}"],
          distcoeffsfisheye: ["(k_1, k_2, k_3, k_4)"],
          hdotsfor: ["\\dots", 1],
          mathbbm: ["\\mathbb{#1}", 1],
          bordermatrix: ["\\matrix{#1}", 1]
      }
  }
}
);
//]]>
</script><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js"></script>
<link href="../../doxygen.css" rel="stylesheet" type="text/css" />
<link href="../../stylesheet.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<!--#include virtual="/google-search.html"-->
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectlogo"><img alt="Logo" src="../../opencv-logo-small.png"/></td>
  <td style="padding-left: 0.5em;">
   <div id="projectname">OpenCV
   &#160;<span id="projectnumber">4.5.2</span>
   </div>
   <div id="projectbrief">Open Source Computer Vision</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.13 -->
<script type="text/javascript">
var searchBox = new SearchBox("searchBox", "../../search",false,'Search');
</script>
<script type="text/javascript" src="../../menudata.js"></script>
<script type="text/javascript" src="../../menu.js"></script>
<script type="text/javascript">
$(function() {
  initMenu('../../',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="../../d3/d81/tutorial_contrib_root.html">Tutorials for contrib modules</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="headertitle">
<div class="title">Omnidirectional Camera Calibration </div>  </div>
</div><!--header-->
<div class="contents">
<div class="textblock"><p>This module includes calibration, rectification and stereo reconstruction of omnidirectional camearas. The camera model is described in this paper:</p>
<p><em>C. Mei and P. Rives, Single view point omnidirectional camera calibration from planar grids, in ICRA 2007.</em></p>
<p>The model is capable of modeling catadioptric cameras and fisheye cameras, which may both have very large field of view.</p>
<p>The implementation of the calibration part is based on Li's calibration toolbox:</p>
<p><em>B. Li, L. Heng, K. Kevin and M. Pollefeys, "A Multiple-Camera System Calibration Toolbox Using A Feature Descriptor-Based Calibration Pattern", in IROS 2013.</em></p>
<p>This tutorial will introduce the following parts of omnidirectional camera calibartion module:</p>
<ul>
<li>calibrate a single camera.</li>
<li>calibrate a stereo pair of cameras.</li>
<li>rectify images so that large distoration is removed.</li>
<li>reconstruct 3D from two stereo images, with large filed of view.</li>
<li>comparison with fisheye model in opencv/calib3d/</li>
</ul>
<h2>Single Camera Calibration </h2>
<p>The first step to calibrate camera is to get a calibration pattern and take some photos. Several kinds of patterns are supported by OpenCV, like checkerborad and circle grid. A new pattern named random pattern can also be used, you can refer to opencv_contrib/modules/ccalib for more details.</p>
<p>Next step is to extract corners from calibration pattern. For checkerboard, use OpenCV function <code><a class="el" href="../../d9/d0c/group__calib3d.html#ga93efa9b0aa890de240ca32b11253dd4a" title="Finds the positions of internal corners of the chessboard. ">cv::findChessboardCorners</a></code>; for circle grid, use <code><a class="el" href="../../d9/d0c/group__calib3d.html#ga7f02cd21c8352142890190227628fa80" title="Finds centers in the grid of circles. ">cv::findCirclesGrid</a></code>, for random pattern, use the <code>randomPatternCornerFinder</code> class in opencv_contrib/modules/ccalib/src/randomPattern.hpp. Save the positions of corners in images in a variable like <code>imagePoints</code>. The type of <code>imagePoints</code> may be <code>std::vector&lt;std::vector&lt;<a class="el" href="../../dc/d84/group__core__basic.html#ga392bb4f8a6b9e0dde07f31dc28e73319">cv::Vec2f</a>&gt;&gt;</code>, the first vector stores corners in each frame, the second vector stores corners in an individual frame. The type can also be <code>std::vector&lt;<a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a>&gt;</code> where the <code><a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a></code> is <code>CV_32FC2</code>.</p>
<p>Also, the corresponding 3D points in world (pattern) coordinate are required. You can compute they for yourself if you know the physical size of your pattern. Save 3D points in <code>objectPoints</code>, similar to <code>imagePoints</code>, it can be <code>std::vector&lt;std::vector&lt;Vec3f&gt;&gt;</code> or <code>std::vector&lt;<a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a>&gt;</code> where <code><a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a></code> is of type <code>CV_32FC3</code>. Note the size of <code>objectPoints</code> and <code>imagePoints</code> must be the same because they are corresponding to each other.</p>
<p>Another thing you should input is the size of images. The file opencv_contrib/modules/ccalib/tutorial/data/omni_calib_data.xml stores an example of objectPoints, imagePoints and imageSize. Use the following code to load them:</p>
<div class="fragment"><div class="line">cv::FileStorage fs(&quot;omni_calib_data.xml&quot;, cv::FileStorage::READ);</div><div class="line">std::vector&lt;cv::Mat&gt; objectPoints, imagePoints;</div><div class="line">cv::Size imgSize;</div><div class="line">fs[&quot;objectPoints&quot;] &gt;&gt; objectPoints;</div><div class="line">fs[&quot;imagePoints&quot;] &gt;&gt; imagePoints;</div><div class="line">fs[&quot;imageSize&quot;] &gt;&gt; imgSize;</div></div><!-- fragment --><p>Then define some variables to store the output parameters and run the calibration function like:</p>
<div class="fragment"><div class="line">cv::Mat K, xi, D, idx;</div><div class="line">int flags = 0;</div><div class="line">cv::TermCriteria critia(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 200, 0.0001);</div><div class="line">std::vector&lt;cv::Mat&gt; rvecs, tvecs;</div><div class="line">double rms = cv::omnidir::calibrate(objectPoints, imagePoints, imgSize, K, xi, D, rvecs, tvecs, flags, critia, idx);</div></div><!-- fragment --><p><code>K</code>, <code>xi</code>, <code>D</code> are internal parameters and <code>rvecs</code>, <code>tvecs</code> are external parameters that store the pose of patterns. All of them have depth of <code>CV_64F</code>. The <code>xi</code> is a single value variable of Mei's model. <code>idx</code> is a <code>CV_32S</code> Mat that stores indices of images that are really used in calibration. This is due to some images are failed in the initialization step so they are not used in the final optimization. The returned value <em>rms</em> is the root mean square of reprojection errors.</p>
<p>The calibration supports some features, <em>flags</em> is a enumeration for some features, including:</p>
<ul>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aaf70dfa2a5c442e4f2b3992183f58db57">cv::omnidir::CALIB_FIX_SKEW</a></li>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aae0cda4a468b2dd7d5bf8d25b59af842d">cv::omnidir::CALIB_FIX_K1</a></li>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aae06ee285ec34e44f896f14411921b4a2">cv::omnidir::CALIB_FIX_K2</a></li>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aa797a57203db40b8abf59e406c5115caa">cv::omnidir::CALIB_FIX_P1</a></li>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aa6209b9a3475764750722a1de1eede165">cv::omnidir::CALIB_FIX_P2</a></li>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aab995c1b213d289aa8d4dd3cfba8b9c73">cv::omnidir::CALIB_FIX_XI</a></li>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aa9032c7d629be0a896e942f14670919c2">cv::omnidir::CALIB_FIX_GAMMA</a></li>
<li><a class="el" href="../../d3/ddc/group__ccalib.html#ggab1335ff41f89604e6e1706fbad77ba0aa2a44eb74b27a87e8e0049ffcfcf8ed02">cv::omnidir::CALIB_FIX_CENTER</a></li>
</ul>
<p>Your can specify <code>flags</code> to fix parameters during calibration. Use 'plus' operator to set multiple features. For example, <code>CALIB_FIX_SKEW+CALIB_FIX_K1</code> means fixing skew and K1.</p>
<p><code>criteria</code> is the stopping criteria during optimization, set it to be, for example, <a class="el" href="../../d9/d5d/classcv_1_1TermCriteria.html" title="The class defining termination criteria for iterative algorithms. ">cv::TermCriteria</a>(<a class="el" href="../../d9/d5d/classcv_1_1TermCriteria.html#a56fecdc291ccaba8aad27d67ccf72c57aeb9da694ea67b3ef7d524521b580867d" title="the maximum number of iterations or elements to compute ">cv::TermCriteria::COUNT</a> + <a class="el" href="../../d9/d5d/classcv_1_1TermCriteria.html#a56fecdc291ccaba8aad27d67ccf72c57a857609e73e7028e638d2ea649f3b45d5" title="the desired accuracy or change in parameters at which the iterative algorithm stops ...">cv::TermCriteria::EPS</a>, 200, 0.0001), which means using 200 iterations and stopping when relative change is smaller than 0.0001.</p>
<h2>Stereo Calibration </h2>
<p>Stereo calibration is to calibrate two cameras together. The output parameters include camera parameters of two cameras and the relative pose of them. To recover the relative pose, two cameras must observe the same pattern at the same time, so the <code>objectPoints</code> of two cameras are the same.</p>
<p>Now detect image corners for both cameras as discussed above to get <code>imagePoints1</code> and <code>imagePoints2</code>. Then compute the shared <code>objectPoints</code>.</p>
<p>An example of of stereo calibration data is stored in opencv_contrib/modules/ccalib/tutorial/data/omni_stereocalib_data.xml. Load the data by </p><div class="fragment"><div class="line">cv::FileStorage fs(&quot;omni_stereocalib_data.xml&quot;, cv::FileStorage::READ);</div><div class="line">std::vector&lt;cv::Mat&gt; objectPoints, imagePoints1, imagePoints2;</div><div class="line">cv::Size imgSize1, imgSize2;</div><div class="line">fs[&quot;objectPoints&quot;] &gt;&gt; objectPoints;</div><div class="line">fs[&quot;imagePoints1&quot;] &gt;&gt; imagePoints1;</div><div class="line">fs[&quot;imagePoints2&quot;] &gt;&gt; imagePoints2;</div><div class="line">fs[&quot;imageSize1&quot;] &gt;&gt; imgSize1;</div><div class="line">fs[&quot;imageSize2&quot;] &gt;&gt; imgSize2;</div></div><!-- fragment --><p>Then do stereo calibration by </p><div class="fragment"><div class="line">cv::Mat K1, K2, xi1, xi2, D1, D2;</div><div class="line">int flags = 0;</div><div class="line">cv::TermCriteria critia(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 200, 0.0001);</div><div class="line">std::vector&lt;cv::Mat&gt; rvecsL, tvecsL;</div><div class="line">cv::Mat rvec, tvec;</div><div class="line">double rms = cv::omnidir::stereoCalibrate(objectPoints, imagePoints1, imagePoints2, imgSize1, imgSize2, K1, xi1, D1, K2, xi2, D2, rvec, tvec, rvecsL, tvecsL, flags, critia, idx);</div></div><!-- fragment --><p> Here <code>rvec</code> and <code>tvec</code> are the transform between the first and the second camera. <code>rvecsL</code> and <code>tvecsL</code> are the transforms between patterns and the first camera.</p>
<h2>Image Rectificaiton </h2>
<p>Omnidirectional images have very large distortion, so it is not compatible with human's eye balls. For better view, rectification can be applied if camera parameters are known. Here is an example of omnidirectional image of 360 degrees of horizontal field of view.</p>
<div class="image">
<img src="../../sample.jpg" alt="sample.jpg"/>
<div class="caption">
image</div></div>
<p> After rectification, a perspective like view is generated. Here is one example to run image rectification in this module:</p>
<div class="fragment"><div class="line">cv::omnidir::undistortImage(distorted, undistorted, K, D, xi, int flags, Knew, new_size)</div></div><!-- fragment --><p>The variable <em>distorted</em> and <em>undistorted</em> are the origional image and rectified image perspectively. <em>K</em>, <em>D</em>, <em>xi</em> are camera parameters. <em>KNew</em> and <em>new_size</em> are the camera matrix and image size for rectified image. <em>flags</em> is the rectification type, it can be:</p>
<ul>
<li>RECTIFY_PERSPECTIVE: rectify to perspective images, which will lose some filed of view.</li>
<li>RECTIFY_CYLINDRICAL: rectify to cylindrical images that preserve all view.</li>
<li>RECTIFY_STEREOGRAPHIC: rectify to stereographic images that may lose a little view.</li>
<li>RECTIFY_LONGLATI: rectify to longitude-latitude map like a world map of the earth. This rectification can be used to stereo reconstruction but may not be friendly for view. This map is described in paper: <em>Li S. Binocular spherical stereo[J]. Intelligent Transportation Systems, IEEE Transactions on, 2008, 9(4): 589-600.</em></li>
</ul>
<p>The following four images are four types of rectified images discribed above:</p>
<div class="image">
<img src="../../sample_rec_per.jpg" alt="sample_rec_per.jpg"/>
<div class="caption">
image</div></div>
 <div class="image">
<img src="../../sample_rec_cyl.jpg" alt="sample_rec_cyl.jpg"/>
<div class="caption">
image</div></div>
 <div class="image">
<img src="../../sample_rec_ste.jpg" alt="sample_rec_ste.jpg"/>
<div class="caption">
image</div></div>
 <div class="image">
<img src="../../sample_rec_log.jpg" alt="sample_rec_log.jpg"/>
<div class="caption">
image</div></div>
<p> It can be observed that perspective rectified image perserves only a little field of view and is not goodlooking. Cylindrical rectification preserves all field of view and scene is unnatural only in the middle of bottom. The distortion of stereographic in the middle of bottom is smaller than cylindrical but the distortion of other places are larger, and it can not preserve all field of view. For images with very large distortion, the longitude-latitude rectification does not give a good result, but it is available to make epipolar constraint in a line so that stereo matching can be applied in omnidirectional images.</p>
<p><b>Note</b>: To have a better result, you should carefully choose <code>Knew</code> and it is related to your camera. In general, a smaller focal length leads to a smaller field of view and vice versa. Here are recommonded settings.</p>
<p>For RECTIFY_PERSPECTIVE </p><div class="fragment"><div class="line">Knew = Matx33f(new_size.width/4, 0, new_size.width/2,</div><div class="line">               0, new_size.height/4, new_size.height/2,</div><div class="line">               0, 0, 1);</div></div><!-- fragment --><p> For RECTIFY_CYLINDRICAL, RECTIFY_STEREOGRAPHIC, RECTIFY_LONGLATI </p><div class="fragment"><div class="line">Knew = Matx33f(new_size.width/3.1415, 0, 0,</div><div class="line">               0, new_size.height/3.1415, 0,</div><div class="line">               0, 0, 1);</div></div><!-- fragment --><p>Maybe you need to change <code>(u0, v0)</code> to get a better view.</p>
<h2>Stereo Reconstruction </h2>
<p>Stereo reconstruction is to reconstruct 3D points from a calibrated stereo camera pair. It is a basic problem of computer vison. However, for omnidirectional camera, it is not very popular because of the large distortion make it a little difficult. Conventional methods rectify images to perspective ones and do stereo reconstruction in perspective images. However, the last section shows that recifying to perspective images lose too much field of view, which waste the advantage of omnidirectional camera, i.e. large field of view.</p>
<p>The first step of stereo reconstruction is stereo rectification so that epipolar lines are horizontal lines. Here, we use longitude-latitude rectification to preserve all filed of view, or perspective rectification which is available but is not recommended. The second step is stereo matching to get a disparity map. At last, 3D points can be generated from disparity map.</p>
<p>The API of stereo reconstruction for omnidrectional camera is <code>omnidir::stereoReconstruct</code>. Here we use an example to show how it works.</p>
<p>First, calibrate a stereo pair of cameras as described above and get parameters like <code>K1</code>, <code>D1</code>, <code>xi1</code>, <code>K2</code>, <code>D2</code>, <code>xi2</code>, <code>rvec</code>, <code>tvec</code>. Then read two images from the first and second camera respectively, for instance, <code>image1</code> and <code>image2</code>, which are shown below.</p>
<div class="image">
<img src="../../imgs.jpg" alt="imgs.jpg"/>
<div class="caption">
image</div></div>
<p> Second, run <code>omnidir::stereoReconstruct</code> like: </p><div class="fragment"><div class="line">cv::Size imgSize = img1.size();</div><div class="line">int numDisparities = 16*5;</div><div class="line">int SADWindowSize = 5;</div><div class="line">cv::Mat disMap;</div><div class="line">int flag = cv::omnidir::RECTIFY_LONGLATI;</div><div class="line">int pointType = omnidir::XYZRGB;</div><div class="line">// the range of theta is (0, pi) and the range of phi is (0, pi)</div><div class="line">cv::Matx33d KNew(imgSize.width / 3.1415, 0, 0, 0, imgSize.height / 3.1415, 0, 0, 0, 1);</div><div class="line">Mat imageRec1, imageRec2, pointCloud;</div><div class="line"></div><div class="line">cv::omnidir::stereoReconstruct(img1, img2, K1, D1, xi1, K2, D2, xi2, R, T, flag, numDisparities, SADWindowSize, disMap, imageRec1, imageRec2, imgSize, KNew, pointCloud);</div></div><!-- fragment --><p>Here variable <code>flag</code> indicates the recectify type, only <code>RECTIFY_LONGLATI</code>(recommend) and <code>RECTIFY_PERSPECTIVE</code> make sense. <code>numDisparities</code> is the max disparity value and <code>SADWindowSize</code> is the window size of <code><a class="el" href="../../d2/d85/classcv_1_1StereoSGBM.html" title="The class implements the modified H. Hirschmuller algorithm  that differs from the original one as fo...">cv::StereoSGBM</a></code>. <code>pointType</code> is a flag to define the type of point cloud, <code>omnidir::XYZRGB</code> each point is a 6-dimensional vector, the first three elements are xyz coordinate, the last three elements are rgb color information. Another type <code>omnidir::XYZ</code> means each point is 3-dimensional and has only xyz coordiante.</p>
<p>Moreover, <code>imageRec1</code> and <code>imagerec2</code> are rectified versions of the first and second images. The epipolar lines of them have the same y-coordinate so that stereo matching becomes easy. Here are an example of them:</p>
<div class="image">
<img src="../../lines.jpg" alt="lines.jpg"/>
<div class="caption">
image</div></div>
<p>It can be observed that they are well aligned. The variable <code>disMap</code> is the disparity map computed by <code><a class="el" href="../../d2/d85/classcv_1_1StereoSGBM.html" title="The class implements the modified H. Hirschmuller algorithm  that differs from the original one as fo...">cv::StereoSGBM</a></code> from <code>imageRec1</code> and <code>imageRec2</code>. The disparity map of the above two images is:</p>
<div class="image">
<img src="../../disparity.jpg" alt="disparity.jpg"/>
<div class="caption">
image</div></div>
<p> After we have disparity, we can compute 3D location for each pixel. The point cloud is stored in <code>pointCloud</code>, which is a 3-channel or 6-channel <code><a class="el" href="../../d3/d63/classcv_1_1Mat.html" title="n-dimensional dense array class ">cv::Mat</a></code>. We show the point cloud in the following image. </p><div class="image">
<img src="../../pointCloud.jpg" alt="pointCloud.jpg"/>
<div class="caption">
image</div></div>
</div></div><!-- contents -->
<!-- HTML footer for doxygen 1.8.6-->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Apr 2 2021 11:36:38 for OpenCV by &#160;<a href="http://www.doxygen.org/index.html">
<img class="footer" src="../../doxygen.png" alt="doxygen"/>
</a> 1.8.13
</small></address>
<script type="text/javascript">
//<![CDATA[
addTutorialsButtons();
//]]>
</script>
</body>
</html>
